/*
 * #%L
 * Interface
 * %%
 * Copyright (C) 2011 Ractoc.com
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
package com.ractoc.opengamefinder.api.plugins;

import java.io.IOException;

import org.apache.log4j.Logger;

import com.jme3.network.Client;
import com.jme3.network.HostedConnection;
import com.jme3.network.Server;
import com.ractoc.opengamefinder.api.network.ClientServerMessage;
import com.ractoc.opengamefinder.api.serializer.BeanSerializer;
import com.ractoc.opengamefinder.api.translators.TranslatorMap;
import com.ractoc.pffj.api.BasePlugin;
import com.ractoc.pffj.api.BasePluginMessage;

/**
 * This is the base spidermonkey plugin. This is where all the code is placed
 * which the server and the client have in common, like registering all the
 * messages.
 * 
 * @author ractoc
 * @version 0.1
 */
public abstract class BaseSpiderMonkeyPlugin extends BasePlugin {

    private static Logger logger = Logger.getLogger(BaseSpiderMonkeyPlugin.class.getName());
    /**
     * The current client.
     */
    protected Client client;
    /**
     * The current server.
     */
    protected Server server;

    /**
     * This method is used to register all the message classes. There are
     * currently 3 different types of message classes:
     * <ul>
     * <li>Messages</li>
     * <li>Results</li>
     * <li>Value objects</li>
     * </ul>
     */
    protected final void registerClasses() throws ClassNotFoundException {

        BeanSerializer beanSerializer = new BeanSerializer();
        beanSerializer.serialze();
    }

    /**
     * Sends an actual message to either the server or the client.
     * 
     * @param message The message to send.
     * @param originPlugin The plugin the message originated from.
     * @param destinationPlugin The plugin the message is intended for.
     * @param reliable Should the message be sent reliably.
     * @param trusted Should the message be send in a trusted way.
     * @param hostedConnection The client the message is intended for. This is only needed in
     *            case of the server.
     * @throws IOException Something went wrong while sending the message.
     */
    protected final void sendMessage(final BasePluginMessage message, final String originPlugin,
            final String destinationPlugin, final boolean reliable, final boolean trusted,
            final HostedConnection hostedConnection) throws IOException {
        logger.debug("translating message: " + message.getClass().getName());
        final ClientServerMessage nMessage = (ClientServerMessage) TranslatorMap.translate(message);
        logger.debug("translated message to: " + nMessage.getClass().getName());
        nMessage.setOriginPlugin(originPlugin);
        nMessage.setDestinationPlugin(destinationPlugin);
        nMessage.setReliable(reliable);
        logger.debug("message class=" + nMessage.getClass().getName());
        final String logMessageStart = "sending message " + nMessage + " from " + originPlugin;
        if (client != null) {
            logger.info(logMessageStart + " on the client " + client.getId() + " to " + destinationPlugin
                    + " to the server");
            try {
                client.send(nMessage);
            } catch (RuntimeException e) {
                logger.error("Unable to send message", e);
                throw new IOException("Unable to send message", e);
            }
        } else if (server != null) {
            logger.info(logMessageStart + " on the server to " + destinationPlugin + " on client "
                    + hostedConnection.getId());
            try {
                hostedConnection.send(nMessage);
            } catch (RuntimeException e) {
                logger.error("Unable to send message", e);
                throw new IOException("Unable to send message", e);
            }
        } else {
            throw new NullPointerException("Neither a Server nor a Client has been defined.");
        }
    }
}
